package org.example.springgobang.model;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.example.springgobang.SpringGobangApplication;
import org.example.springgobang.game.OnlineUserManager;
import org.example.springgobang.game.RoomManager;
import org.example.springgobang.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import java.io.IOException;
import java.util.UUID;

@Slf4j
@Data
//不能加 @Component 单例模式不符合设计需求
public class Room {
    private String roomId;
    private User player1;
    private User player2;
    // 玩家id
    private int whiteUser;
    private static final int MAX_ROW = 15;
    private static final int MAX_COL = 15;
    private boolean AIGame=false;
    //约定 0 表示未落子 1 代表 player1 的落子 ; 2 代表 player2 的落子
    private int[][] board=new int[MAX_ROW][MAX_COL];


    private ObjectMapper objectMapper=new ObjectMapper();

    private OnlineUserManager onlineUserManager;

    private RoomManager roomManager;

    private UserMapper userMapper;

    public Room(){
        roomId= UUID.randomUUID().toString();
        //通过入口类中记录的 context 来手动获取到前面的 RoomManager 和 OnlineUserManager
        onlineUserManager= SpringGobangApplication.context.getBean(OnlineUserManager.class);
        roomManager= SpringGobangApplication.context.getBean(RoomManager.class);
        userMapper= SpringGobangApplication.context.getBean(UserMapper.class);
    }


    /**处理落子操作*/
    public void putChess(String payload) throws IOException {
        GameRequest request=objectMapper.readValue(payload,GameRequest.class);
        GameResponse response=new GameResponse();

        // 添加AI逻辑
        if (AIGame && request.getUserId() == player1.getUserId()) {
            // 玩家落子后，AI自动落子
            handlePlayerMove(request, response);
            if (response.getWinner() == 0) { // 如果玩家没有获胜，AI继续落子
                handleAIMove(response);
            }
        } else {
            // 正常的双人对战逻辑
            handleNormalMove(request, response);
        }

    }

    private void handleNormalMove(GameRequest request, GameResponse response) throws IOException {
        // 原有的落子逻辑
        int chess = request.getUserId() == player1.getUserId() ? 1 : 2;
        int row = request.getRow();
        int col = request.getCol();
        if(board[row][col]!=0){
            log.info("当前位置：("+row+","+"col"+")已经落子了");
            return;
        }
        board[row][col]=chess;
        //2、打印棋盘信息
        printBoard();
        //3、进行胜负的判定
        int winner = checkWinner(row , col , chess);
        // 4、给该房间中所有客户端返回响应


        response.setMessage("putChess");
        response.setUserId(request.getUserId());
        response.setRow(row);
        response.setCol(col);
        response.setWinner(winner);

        WebSocketSession session1=onlineUserManager.getGameRoom(player1.getUserId());
        WebSocketSession session2=onlineUserManager.getGameRoom(player2.getUserId());
        if (session2==null){
            response.setWinner(player1.getUserId());
            log.info("玩家2"+player2.getUsername()+"掉线，玩家1直接获胜");
        }
        if (session1==null){
            response.setWinner(player2.getUserId());
            log.info("玩家2"+player1.getUsername()+"掉线，玩家2直接获胜");
        }
        if (session1!=null){
            session1.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
        }
        if(session2!=null){
            session2.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
        }

        //5、若存在人获胜，则胜负已分
        if(response.getWinner()!=0){
            int winPlayerId=response.getWinner();
            int losePlayerId=(winPlayerId==player1.getUserId())?player2.getUserId():player1.getUserId();
            userMapper.userWin(winPlayerId);
            userMapper.userLose(losePlayerId);
            //胜负已分
            log.info("游戏结束，销毁当前房间！roomId ={}"+roomId);
            roomManager.remove(roomId, player1.getUserId(), player2.getUserId());
        }
    }
    // 处理玩家落子
    private void handlePlayerMove(GameRequest request, GameResponse response) throws IOException {
        int row = request.getRow();
        int col = request.getCol();
        if(board[row][col]!=0){
            return;
        }
        board[row][col] = 1; // 玩家落子

        response.setMessage("putChess");
        response.setUserId(request.getUserId());
        response.setRow(row);
        response.setCol(col);

        int winner = checkWinner(row, col, 1);
        response.setWinner(winner);

        WebSocketSession session1 = onlineUserManager.getGameRoom(player1.getUserId());
        if(session1 != null){
            session1.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
        }
    }



    // 处理AI落子
    private void handleAIMove(GameResponse lastResponse)  {
        if (lastResponse.getWinner() != 0) return;
        new Thread(()->{
            try {
                // AI思考时间：随机1-2秒
                Thread.sleep(1000 + (long) (Math.random() * 1000));
                AIPlayer aiPlayer = new AIPlayer(board);
                // 简单的AI策略：找到第一个空位置
                int[] move = aiPlayer.getBestMove();
                int row = move[0];
                int col = move[1];

                board[row][col] = 2; // AI落子

                GameResponse response = new GameResponse();
                response.setMessage("putChess");
                response.setUserId(player2.getUserId());
                response.setRow(row);
                response.setCol(col);

                int winner = checkWinner(row, col, 2);
                response.setWinner(winner);

                WebSocketSession session1 = onlineUserManager.getGameRoom(player1.getUserId());
                if (session1 != null) {
                    session1.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
                }
            }catch (InterruptedException | IOException e) {
                log.error("AI下棋出错", e);
            }
        }).start();
    }

    private void printBoard() {
        System.out.println(roomId+"[当前局势]");
        System.out.println("==============================================");
        for (int r = 0; r < MAX_ROW; r++) {
            for (int c = 0; c < MAX_COL; c++) {
                System.out.print(board[r][c]+" ");
            }
            System.out.println();
        }
        System.out.println("==============================================");
    }

    //判断获胜条件 谁胜出 ，返回谁的userId 如果还未分出胜负，返回0
    private int checkWinner(int row, int col, int chess) {
        //1、检查所有行
        //确定最左边的椅子
        for (int c = col - 4; c <= col; c++) {
            try {
                if (board[row][c] == chess
                        && board[row][c + 1] == chess
                        && board[row][c + 2] == chess
                        && board[row][c + 3] == chess
                        && board[row][c + 4] == chess) {
                    return chess == 1 ? player1.getUserId() : player2.getUserId();
                }
            } catch (ArrayIndexOutOfBoundsException e) {
                log.info("数组下标越界");
                continue;
            }
        }
        //2、检查所有列
        for (int r = row-4; r <= row; r++) {
            try {
                if(board[r][col]==chess
                        && board[r+1][col]==chess
                        && board[r+2][col]==chess
                        && board[r+3][col]==chess
                        && board[r+4][col]==chess){
                    return chess == 1 ? player1.getUserId() : player2.getUserId();
                }
            }catch (ArrayIndexOutOfBoundsException e){
                log.info("数组下标越界");
                continue;
            }
        }
        //3、检查正对角线 左下角元素
        for (int r = row-4,c = col-4; r <= row && c<=col; r++,c++) {
            try{
                if(board[r][c]==chess
                && board[r+1][c+1]==chess
                && board[r+2][c+2]==chess
                && board[r+3][c+3]==chess
                && board[r+4][c+4]==chess){
                    return chess == 1 ? player1.getUserId() : player2.getUserId();
                }
            }catch (ArrayIndexOutOfBoundsException e){
                log.info("数组下标越界");
                continue;
            }
        }
        //4、检查副对角线 左上角元素
        for (int r = row-4,c = col+4; r <= row && c>=col; r++,c--) {
            try{
                if(board[r][c]==chess
                        && board[r+1][c-1]==chess
                        && board[r+2][c-2]==chess
                        && board[r+3][c-3]==chess
                        && board[r+4][c-4]==chess){
                    return chess == 1 ? player1.getUserId() : player2.getUserId();
                }
            }catch (ArrayIndexOutOfBoundsException e){
                log.info("数组下标越界");
                continue;
            }
        }
        return 0;
    }


}
